package utils;

import org.apache.commons.text.StringEscapeUtils;
import org.owasp.html.PolicyFactory;
import org.owasp.html.Sanitizers;

import java.util.regex.Pattern;

public class XSSPreventionUtil {
    private static final PolicyFactory POLICY = Sanitizers.FORMATTING.and(Sanitizers.LINKS);

    public static String sanitizeInput(String input) {
        return POLICY.sanitize(input);
    }

    public static String escapeOutput(String input) {
        return StringEscapeUtils.escapeHtml4(input);
    }

    public static void main(String[] args) {
        String userInput = "quick\" onpointerover=\"alert(111)\" Vwr=\"";

        String sanitizedInput = sanitizeInput(userInput);
        // 编码输出
        String safeOutput = escapeOutput(sanitizedInput);
        // 输出经过处理的安全内容
        System.out.println("====>" + safeOutput);

        System.out.println("cleanXSS====>" + cleanXSS(userInput));
    }

    /**
     * 清除xss
     *
     * @param src 单个参数
     * @return
     */
    public static String cleanXSS(String src) {
        String temp = src;
        // 校验xss脚本
        for (Pattern pattern : scriptPatterns) {
            temp = pattern.matcher(temp).replaceAll("");
        }
        // 校验xss特殊字符
        temp = temp.replaceAll("\0|\n|\r", "");
        temp = temp.replaceAll("<", "&lt;").replaceAll(">", "&gt;");

        if (!temp.equals(src)) {
            throw new RuntimeException("xss攻击检查：参数含有非法攻击字符，已禁止继续访问！！");
        }

        return src;
    }

    /**
     * xss脚本正则
     */
    private final static Pattern[] scriptPatterns = {
            Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
            Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
            Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
            Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
            Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
            Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
            Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
            Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
            Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)
    };
}